﻿#include"stdafx.h"
#ifdef LK_REFLECTION_
namespace LK
{
	namespace Reflection
	{
		PTypeNode::PTypeNode(ptr<Type> id, ptr<String> const& name, PDomainNode const&baseNode, weakptr<TypeLibrary> const& library)
			:PDomainNode()
		{
			if (library!=null){//先查找类库中是否有这个类型
				PTypeNode n = library.GetTypeNodeByInfo(id);
				if (n==null)SetTo(new TypeNode(id, name, baseNode, library));
				else//如果有相同类型，则进行内容覆盖
				{
					*this = n;
					if (baseNode!=null)SetBaseNode(baseNode);
					if (library!=null)SetLibrary(library);
					if (!name.IsNullOrEmpty())SetName(name);
				}
			}
			else SetTo(new TypeNode(id, name, baseNode, library));
		}
		ptr<Collection::IArray<PTypeNode>> PTypeNode::GetBaseTypeNodes() const{ return Check()->BaseTypeNodes; }
		void PTypeNode::AddFunction(ptr<String> const&name, Functional::PFunObjs const&fun)const { AddFunction(name, fun, Convert<PDomainNode, ptr<Object>>::RefFrom(ptr<Object>())); }
		void PTypeNode::AddFunction(ptr<String> const&name, Functional::PFunObjs const&fun, PDomainNode domain)const
		{
			Check()->AddFunction(name, fun,domain);
		}
		void PTypeNode::AddBaseType(ptr<Type> const & node) const{ Check()->AddBaseType(node); }
		bool PTypeNode::IsDerivedFrom(PTypeNode n)const{ return Check()->IsDerivedFrom(n); }
		bool PTypeNode::CanConvertTo(ptr<Type> t, bool isExplicit)const { return Check()->CanConvertTo(t, isExplicit); }
		bool PTypeNode::CanConstructFrom(ptr<Collection::IArray<ptr<Type>>>const&args, bool isExplicit )const { return Check()->CanConstructFrom(args, isExplicit); }
		ptr<Object> PTypeNode::DynamicConvertTo(ptr<Type> dest, ptr<Object> const&source, bool isExplicit )const { return Check()->DynamicConvertTo(dest,source, isExplicit); }
		ptr<Object> PTypeNode::DynamicConstructFrom(ptr<Collection::IArray<ptr<Object>>>const&source, bool isExplicit )const { return Check()->DynamicConstructFrom(source, isExplicit); }
		ptr<LibraryNode> PTypeNode::FindNodeByNameInClass(ptr<String> const&name)const{ return Check()->FindNodeByNameInClass(name); }
		size_t & PTypeNode::GetSizeRef() const
		{
			return Check()->Size;
		}
		index_t PTypeNode::CompareId(PTypeNode const & t, index_t id)
		{
			return t==null?-1:(t->GetType()->GetID() - id);
		}
		void PTypeNode::AddOperatorFunction(const Functional::PFunObjs&fun) { Check()->AddOperatorFunction(fun); }
		void PTypeNode::AddConstructFunction(const Functional::PFunObjs&fun) { Check()->AddConstructFunction(fun); }
		PFunctionNode PTypeNode::GetOperatorFunctions()const { return Check()->GetOperatorFunctions(); }
		PFunctionNode PTypeNode::GetConstructFunctions()const { return Check()->GetConstructFunctions(); }
		void PTypeNode::RemoveDerivedNode(PTypeNode const&node)const{Check()->RemoveDerivedNode(node);}

		TypeNode::TypeNode(ptr<Type> id, ptr<String> const& name, PDomainNode const&baseNode, weakptr<TypeLibrary> const& library)
			:DomainNode(library, baseNode, name), Size(0) , Id(id){
			if (id==null)Throw<PInvalidArgumentException>(L"类型ID不得为NULL");
		}
		void TypeNode::Clear()
		{
			if (DerivedTypeNodes!=null)
			{
				for (index_t i = 0; i < DerivedTypeNodes->size(); ++i)
					DerivedTypeNodes[i].Clear();
				DerivedTypeNodes=null;
			}
			if (BaseTypeNodes!=null)
			{
				PTypeNode*p = BaseTypeNodes;
				index_t len = BaseTypeNodes->size();
				for (index_t i = 0; i < len; ++i)if (p[i]!=null)p[i].RemoveDerivedNode(this);
				BaseTypeNodes=null;
			}
			if (OperatorFunctions!=null)OperatorFunctions.Clear();
			if (ConstructFunctions!=null)ConstructFunctions.Clear();
			DomainNode::Clear();
		}

		void TypeNode::AddBaseType(ptr<Type> const & tp)
		{
			PTypeNode node = GetLibrary().GetTypeNodeByInfo(tp);
			if (Object::ReferenceEqual(node, this))Throw<PInvalidArgumentException>(L"一个类不能是自己的基类");
			if (Object::ReferenceEqual(node, GetBaseNode()))return;
			if (BaseTypeNodes==null)BaseTypeNodes = new Collection::DefaultArray<PTypeNode>();
			index_t idx = BaseTypeNodes->IndexOf(node);
			if (idx >= 0)return;//已经存在该基类
			//加入基类
			BaseTypeNodes->Append(node);
			//为该类型和派生类型添加基类的方法
			ptr<Collection::IArray<ptr<LibraryNode>>>& rarr = node.GetInnerNodesRef();
			if (rarr!=null){
				index_t len = rarr->size();
				ptr<LibraryNode>* p = rarr;
				for (idx = 0; idx < len; ++idx){
					PFunctionNode f = cast<PFunctionNode>(p[idx]);
					if (f!=null) {
						ptr<Collection::IArray<Functional::PFunObjs>> fs = f->Methods;
						ptr<String> name = f->GetName();
						if (fs!=null){
							for (index_t i = 0; i < fs->size();++i)
								AddFunction(name, fs[i],node);
						}
					}
				}
			}
			//在基类的派生类列表中添加该类
			if (node.GetPtr()->DerivedTypeNodes==null)node.GetPtr()->DerivedTypeNodes = new LK::Collection::DefaultArray<PTypeNode>(1, this);
			else{
				index_t i = node.GetPtr()->DerivedTypeNodes->DichotomyIndexOf(this, &ptr<LibraryNode>::Compare);
				if (i < 0)node.GetPtr()->DerivedTypeNodes->DichotomyInsertAsc(this, &ptr<LibraryNode>::Compare);
				else node.GetPtr()->DerivedTypeNodes[i] = this;
			}
		}
		bool TypeNode::IsDerivedFrom(PTypeNode n)const
		{
			if (Object::ReferenceEqual(this, n))return true; //认为跟本身进行派生判断为true
			if (BaseTypeNodes==null || n==null)return false;
			for (index_t i = 0; i < BaseTypeNodes->size(); ++i)
				if (Object::ReferenceEqual(BaseTypeNodes[i], n) || BaseTypeNodes[i].IsDerivedFrom(n))return true;
			return false;
		}
		void TypeNode::SetLibrary(weakptr<TypeLibrary> const&lib)
		{
			if (Object::ReferenceEqual(lib, GetLibrary()))return;
			if (GetLibrary()!=null)GetLibrary().SetTypeNodeByInfo(Id, PTypeNode());
			LibraryNode::SetLibrary(lib);
			if (lib!=null)lib.SetTypeNodeByInfo(Id, this);
		}
		void TypeNode::AddFunction(ptr<String> const&name, Functional::PFunObjs fun) { AddFunction(name, fun,Convert<PDomainNode, ptr<Object>>::RefFrom(ptr<Object>())); }
		void TypeNode::AddFunction(ptr<String> const&name, Functional::PFunObjs fun, PDomainNode domain)
		{
			if (name.IsNullOrEmpty() || fun==null)Throw<PInvalidArgumentException>(L"传入的函数名或函数为空");
			ptr<LibraryNode> node= GetInnerNodeByName(name);
			if (node==null)node=AddInnerNode(new FunctionNode(name));
			else if (cast<PFunctionNode>(node)==null)Throw<PReflectionException >(L"类中已存在同名成员");
			void*p; fun->GetInnerPtr(&p);
			if (p){
				Throw<PReflectionException >(L"所指定的成员函数的对象指针非空");
            }
			if (((PFunctionNode&)node).AddFunction(fun, domain) && DerivedTypeNodes!=null)
				for (index_t i = 0; i < DerivedTypeNodes->size(); ++i)DerivedTypeNodes[i].AddFunction(name, fun, domain);
		}
		ptr<LibraryNode> TypeNode::FindNodeByNameInClass(ptr<String> const&name)const
		{
			ptr<LibraryNode> node = GetInnerNodeByName(name);
			if (node!=null || BaseTypeNodes==null)return node;
			for (index_t i = 0; i < BaseTypeNodes->size();++i)
				if((node = BaseTypeNodes[i].FindNodeByNameInClass(name))!=null)break;
			return node;
		}
		void TypeNode::RemoveDerivedNode(PTypeNode const&node)
		{//TODO 移除派生关系时，派生类中有可能残留该类型方法
			if (DerivedTypeNodes==null || node==null)return;
			index_t i = DerivedTypeNodes->DichotomyIndexOf<PTypeNode const&>(node, &ptr<LibraryNode>::Compare);
			if (i < 0)return;
			DerivedTypeNodes->RemoveAt(i);
		}

		bool TypeNode::CanConvertTo(ptr<Type> t, bool isExp)const
		{
			if (t==null)return false;
			PTypeNode node = (TypeNode*)this;
			if (node.GetPtr()->Id->CompareWithoutExtents(t) == 0)return true;
			if (node.GetPtr()->GetOperatorFunctions()!=null) {
				ptr<Collection::IArray<Functional::PFunObjs>>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
				index_t i = arr->DichotomyIndexOf(t, &FunctionNode::OperatorCompare);
				if (i >= 0)return true;
			}
			//当isExp为false时进行模糊查询
			if (!isExp)
			{
				if (node.GetPtr()->GetOperatorFunctions()!=null) {
					ptr<Collection::IArray<Functional::PFunObjs>>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
					for (index_t i = 0; i < arr->size(); ++i)
						if (t->CanDynamicConvertFrom(arr[i]->GetArgsType()[0], 1))return true;
				}
			}
			return false;
		}
		bool TypeNode::CanConstructFrom(ptr<Collection::IArray<ptr<Type>>>const& t,bool isExp)const
		{
			if (GetConstructFunctions()!=null) {
				return GetConstructFunctions().GetFunction(t,isExp)!=null;
			}
			return false;
		}
		ptr<Object> TypeNode::DynamicConvertTo(ptr<Type> t, ptr<Object> const&source,bool isExp)const
		{
			if (t==null)Throw<PInvalidArgumentException>(L"指定的目标类型为空");
			PTypeNode node = (TypeNode*)this;
			if (node.GetPtr()->Id->CompareWithoutExtents(t) == 0)return Type::SameTypeReferenceConvert(node.GetPtr()->Id,source);
			if (node.GetPtr()->GetOperatorFunctions()!=null) {
				ptr<Collection::IArray<Functional::PFunObjs>>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
				index_t i = arr->DichotomyIndexOf(t, &FunctionNode::OperatorCompare);
				if (i >= 0)
				{
					ptr<Collection::IArray<ptr<Type>>> tarr;
					bool bf = false;
				ReFind:;
					tarr = arr[i]->GetArgsType();
					if (i > 0 && tarr[0] > t) { i--; bf = true; if (tarr[0]->CompareWithoutExtents(t) == 0)goto ReFind; }
					else if (i < arr->size() && tarr[0] < t) { i++; if (!bf&&tarr[0]->CompareWithoutExtents(t) == 0)goto ReFind; }
					Collection::ReferenceArray<ptr<Object>> arg(1, &source);
					return arr[i]->Call(source, &arg);
				}
			}
			if (!isExp)
			{
				if (node.GetPtr()->GetOperatorFunctions()!=null) {
					ptr<Collection::IArray<Functional::PFunObjs>>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
					for (index_t i = 0; i < arr->size(); ++i)
						if (t->CanDynamicConvertFrom(arr[i]->GetArgsType()[0], 1))
						{
							Collection::FixedArray<ptr<Object>, sizeof(size_t)> arg(1, &source);
							return arr[i]->Call(ptr<Object>(), &arg);
						}
				}
			}
			return RThrow<ptr<Object>, PTypesConvertErrorException>(L"无法进行从类型 "+Id->GetFullName()+L" 到类型 "+t->GetFullName()+L"的转换，缺少相应的转换函数");
		}
		ptr<Object> TypeNode::DynamicConstructFrom(ptr<Collection::IArray<ptr<Object>>>const&source,bool isExp)const{
			ptr<Collection::IArray<ptr<Type>>>tarr;
			if (source!=null)
			{
				tarr = new LK::Collection::DefaultArray<ptr<Type>>(source->size());
				for (index_t i = 0; i < tarr->size(); ++i)
				{
					tarr[i] = source[i]->GetType();
					if (tarr[i] == Type::Make<PMObjects>())
						tarr[i] = ((PMObjects&)source[i])->GetInnerType();
				}
			}
			Functional::PFunObjs f;
			if (GetConstructFunctions()!=null) {
				f = GetConstructFunctions().GetFunction(tarr, isExp);
			}
			if (f==null)
			{
				ptr<String> str = L"(";
				for (index_t i = 0; i < tarr->size(); ++i)
				{
					str += tarr[i]->GetFullName();
					if (i != tarr->size() - 1)str += L",";
				}
				str += L")";
				Throw <PTypesConvertErrorException>(L"无法从类型列表 " +str+ L" 构造类型 " + Id->GetFullName());
			}
			return f->Call(ptr<Object>(), source);
		}
		void TypeNode::AddOperatorFunction(const Functional::PFunObjs&fun)
		{
			ptr<Collection::IArray<ptr<Type>>> tarr = fun->GetArgsType();
			//动态类型检查
			if (tarr->size() != 3 || !tarr[2]->CanDynamicConvertFrom(Id) || tarr[0]==Type::Make<void>())Throw<PReflectionException >(L"类型转换函数必须可以动态传入被转换类型，返回目标类型");
			if (OperatorFunctions==null)OperatorFunctions = new FunctionNode(GetName(), GetLibrary(), this);
			else{//如果已经有目标类型一样的转换函数，则会被跳过
				for (index_t i = 0; i < OperatorFunctions->Methods->size(); ++i)
					if (OperatorFunctions->Methods[i]->GetArgsType()[0] == tarr[0])return;
			}
			if (OperatorFunctions.AddOperatorFunction(fun))//如果是第一次添加
			{
				//为目标类型添加构造函数
				ptr<Type> t = tarr[0];
				if (t->IsPureTypeIgnoreExtents())
				{
					PTypeNode n = GetLibrary().GetTypeNodeByInfo(t->GetID());
					if (n!=null)n.AddConstructFunction(fun);
				}
			}
			//为派生类添加转换方法
			if (DerivedTypeNodes!=null)
			{
				for (index_t i = 0; i < DerivedTypeNodes->size(); ++i)
					DerivedTypeNodes[i].AddOperatorFunction(fun);
			}
		}
		void TypeNode::AddConstructFunction(const Functional::PFunObjs&fun)
		{
			ptr<Collection::IArray<ptr<Type>>> tarr = fun->GetArgsType();
			//动态类型检查
			if (!Id->CanDynamicConvertFrom( tarr[0] ))Throw<PReflectionException >(L"构造函数的返回值类型必须可以动态转换到该类型");
			if (ConstructFunctions==null)ConstructFunctions = new FunctionNode(GetName(), GetLibrary(), this);
			if (ConstructFunctions.AddFunction(fun)&& tarr->size()==3)//如果是第一次添加且参数符合
			{
				//为参数类型添加转换函数
				ptr<Type> t = tarr[2];
				if (t->IsPureTypeIgnoreExtents())
				{
					PTypeNode n = GetLibrary().GetTypeNodeByInfo(t->GetID());
					if (n!=null)n.AddOperatorFunction(fun);
				}
			}
		}

	}
}
#endif
